package com.bazaaroid.mobile.android.db;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;

import com.bazaaroid.mobile.android.helper.AdvancedSearchParser;
import com.bazaaroid.mobile.db.model.partner.*;


import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

/*import com.google.appengine.api.datastore.Email;
import com.google.appengine.api.datastore.Link;
import com.google.appengine.api.datastore.PhoneNumber;*/

public class DbBazaaAdapter {
	private DbBazaaHelper dbBazaaHelper;
	private SQLiteDatabase db;
	private final Context context;
	private String TAG = "[DbBazaaAdapter]";
	
	private static String DATABASE_NAME = "Bazaa";
	private static int DATABASE_VERSION = 1;
	
	public DbBazaaAdapter(Context context)
	{
		Log.d("DbBazaaAdapter", "Entered c-tor...");
		this.context = context;
		dbBazaaHelper = new DbBazaaHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
	}
	
	public ArrayList<Product> doQueryProducts(String queryName)
	{
		// Search only for products
		try
		{
			
			ArrayList<Product> foundProducts = new ArrayList<Product>();
			
			Log.d(TAG, String.format("Searching for '%s'...", queryName));
			
			Cursor productsCursor = dbBazaaHelper.getProducts(queryName);
			Cursor partnerCursor = null;
			Cursor discountCursor = null;
			
			int productCnt = productsCursor.getCount();
			
			Log.d(TAG, String.format("Found %d products.", productCnt));
			
			productsCursor.moveToFirst();
			int cnt = 0;
			while(!productsCursor.isAfterLast())
			{
				Log.d(TAG, String.format("Current number of items in the list: %d", ++cnt));
				Log.d(TAG, String.format("Adding item '%s'", productsCursor.getString(1)));
				Product product = new Product();
				product.setName(productsCursor.getString(1));			// Name
				product.setDescription(productsCursor.getString(2));	// Description
				product.setPrice(productsCursor.getDouble(4));			// Price
				product.setCurrency(productsCursor.getString(5));		// Currency
				// partner
				partnerCursor = dbBazaaHelper.getPartner(productsCursor.getInt(3));	// Partner
				Partner partner = new Partner();
				partner.setName(partnerCursor.getString(1));
				partner.setDescription(partnerCursor.getString(2));
				partner.setContact(null); // contact..
				// discount 
				/*discountCursor = dbBazaaHelper.getDiscount(productsCursor.getInt(6));
				Discount discount = new Discount();*/
				
				product.setPartner(partner);
				
				foundProducts.add(product);
				partnerCursor.close();
				productsCursor.moveToNext();
			}
			/*for(int i = 0; i < productCnt; ++i)
			{
				foundProducts.add(productsCursor.)
			}*/
			
			if(partnerCursor != null)
				partnerCursor.close();
			
			if(productsCursor != null)
				productsCursor.close();
			
			return foundProducts;
			
		}
		catch(Exception e)
		{
			Log.e(TAG, e.getMessage());
		}
		return new ArrayList<Product>();
	}
	
	public ArrayList<Product> doAdvancedQueryProducts(AdvancedSearchParser advancedSearchParser)
	{
		// TODO: to be implemented!!!
		return new ArrayList<Product>();
	}
	
	// Za sada izcitava samo sve partnere, ne pojedinacne
	public ArrayList<Partner> doQueryPartners(String queryName)
	{
		// Search only for products
		try
		{
			
			ArrayList<Partner> foundPartners = new ArrayList<Partner>();
			
			Log.d(TAG, String.format("Searching for '%s'...", queryName));
			
			Cursor partnersCursor = dbBazaaHelper.getPartners();
			
			int partnerCnt = partnersCursor.getCount();
			
			Log.d(TAG, String.format("Found %d partners.", partnerCnt));
			
			partnersCursor.moveToFirst();
			int cnt = 0;
			while(!partnersCursor.isAfterLast())
			{
				Log.d(TAG, String.format("Current number of items in the list: %d", ++cnt));
				Log.d(TAG, String.format("Adding item '%s'", partnersCursor.getString(1)));
				Partner partner = new Partner();
				partner.setName(partnersCursor.getString(1));			// Name
				partner.setDescription(partnersCursor.getString(2));	// Description
				// TODO: izcitavanje contact-a (za sada nije potrebno)
				partner.setContact(null);								// Contact
				
				foundPartners.add(partner);
				partnersCursor.moveToNext();
			}
			
			if(partnersCursor != null)
				partnersCursor.close();
			
			return foundPartners;
			
		}
		catch(Exception e)
		{
			Log.e(TAG, e.getMessage());
		}
		return new ArrayList<Partner>();
	}
	
	public ArrayList<String> doQuery(String query)
	{
		// Search only for products
		try
		{
			
			ArrayList<String> foundProducts = new ArrayList<String>();
			
			Log.d(TAG, String.format("Searching for '%s'...", query));
			
			Cursor productsCursor = dbBazaaHelper.getProducts(query);
			
			int productCnt = productsCursor.getCount();
			
			Log.d(TAG, String.format("Found %d products.", productCnt));
			
			productsCursor.moveToFirst();
			int cnt = 0;
			while(!productsCursor.isAfterLast())
			{
				Log.d(TAG, String.format("Current number of items in the list: %d", ++cnt));
				Log.d(TAG, String.format("Adding item '%s'", productsCursor.getString(1)));
				foundProducts.add(productsCursor.getString(1)); // 1 -> "Name" column
				productsCursor.moveToNext();
			}
			/*for(int i = 0; i < productCnt; ++i)
			{
				foundProducts.add(productsCursor.)
			}*/
			return foundProducts;
			
		}
		catch(Exception e)
		{
			Log.e(TAG, e.getMessage());
		}
		return new ArrayList<String>();
	}
	
	public void initDatabase()
	{
		boolean bToInitialize = false;
		// check if database exists and if tables are filled with dummy data
		
		long addressCount = countAddresses();
		bToInitialize = (addressCount == 0);
		if(bToInitialize)
		{
			
			
			ArrayList<Category> listCategories = new ArrayList<Category>();
			ArrayList<Address> listAddresses = new ArrayList<Address>();
			ArrayList<Contact> listContacts = new ArrayList<Contact>();
			ArrayList<Partner> listPartners = new ArrayList<Partner>();
			ArrayList<Location> listLocations = new ArrayList<Location>();
			ArrayList<Product> listProducts = new ArrayList<Product>();
			ArrayList<Discount> listDiscounts = new ArrayList<Discount>();
			
			// Init categories
			for(int i = 0; i < 20; ++i)
			{
				Category category = new Category();
				category.setName(String.format("Category_%d", i));
				Log.d(TAG, String.format("Adding category: %s", category.getName()));
				addCategory(category);
				listCategories.add(category);
			}
		
			// Init address
			for(int i = 0; i < 50; ++i)
			{
				Address address = new Address();
				address.setStreet(String.format("Street_%d", i));
				address.setNumber(String.format("50/%d", i));
				address.setCity(String.format("City_%d", i));
				address.setPostalCode(String.format("11000_%d", i));
				address.setTownship(String.format("Township_%d", i));
				address.setState(String.format("State_%d", i));
				address.setCountry(String.format("Country_%d", i));
				Log.d(TAG, String.format("Adding address: %s, %s, %s...", address.getStreet(), address.getNumber(), address.getCity()));
				addAddress(address);
				listAddresses.add(address);
			}
			
			// Init contact & partner
			for(int i = 0; i < 50; ++i)
			{
				Contact contact = new Contact();
				contact.setTelephone(String.format("+38111555%d", i));
				contact.setMobile(String.format("+38164555%d", i));
				contact.setFax(String.format("+38111666%d", i));
				contact.setEmail(String.format("email_%d@bazaaroid.com", i));
				contact.setSite(String.format("http://site_%d.bazaaroid.com/", i));
				Log.d(TAG, String.format("Adding contact: %s, %s, %s...", contact.getTelephone(), contact.getMobile(), contact.getEmail()));
				addContact(contact);
				listContacts.add(contact);
				
				if(i > 15 && i < 45)
				{
					Partner partner = new Partner();
					partner.setName(String.format("Name_%d", i));
					partner.setDescription(String.format("Description_%d", i));
					Log.d(TAG, String.format("Adding partner: %s, %s", partner.getName(), partner.getDescription()));
					addPartner(partner, contact);
					listPartners.add(partner);
				}
			}
		
			// Init location
			int initLatitude = 44813453;
			int initLongitude = 20409928;
			int deltaLatitude = 4000;
			int deltaLongitude = 100;
			int curLatitude, curLongitude;
			Random randomGenerator = new Random(2010);
			for(int i = 0; i < listPartners.size(); ++i)
			{
				curLatitude = initLatitude + randomGenerator.nextInt(deltaLatitude);
				curLongitude = initLongitude + randomGenerator.nextInt(deltaLongitude);
				
				Location location = new Location();
				location.setName(String.format("Location_%d", i));
				location.setGeoPoint(new GeoPt(curLatitude, curLongitude));
				location.setOpeningHours(String.format("From 10:%2d untill 20:%2d", i, i));
				location.setAddress(listAddresses.get(i));
				location.setPartner(listPartners.get(i));
				
				Log.d(TAG, String.format("Adding location: %d, %d, '%s', %s, %s", location.getGeoPoint().getLatitude(), location.getGeoPoint().getLongitude(), 
						location.getOpeningHours(), location.getAddress().getStreet(), location.getPartner().getName()));
				addLocation(location, location.getAddress(), location.getPartner());
				listLocations.add(location);
			}
			
			// Init product
			for(int i = 0; i < 100; ++i)
			{
				Product product = new Product();
				product.setName(String.format("Name_%d", i));
				product.setDescription(String.format("Description_%2d", i));
				product.setPartner(listPartners.get(randomGenerator.nextInt(listPartners.size())));
				product.setPrice(randomGenerator.nextDouble());
				product.setCurrency("DCR");
				product.setDiscount(randomGenerator.nextInt(20));
				
				Log.d(TAG, String.format("Adding product: %s, %s, %f, %s, %d", 
						product.getName(), product.getDescription(), product.getPrice(), product.getCurrency(), product.getDiscount()));
				addProduct(product, product.getPartner());
				listProducts.add(product);
			}
			
			// Init discount
			for(int i = 0; i < 20; ++i)
			{
				Discount discount = new Discount();
				discount.setName(String.format("Name_%2d", i));
				discount.setDescription(String.format("Description_%2d", i));
				discount.setPercentage(randomGenerator.nextInt(70));
				discount.setPriceWithDiscount(randomGenerator.nextDouble());
				Discount.TimePeriod timePeriod = new Discount.TimePeriod();
				timePeriod.setDateFrom(new Date());
				timePeriod.setDateTo(new Date());
				discount.setTimePeriod(timePeriod);
				discount.setProduct(randomGenerator.nextInt(listProducts.size()));
				
				Log.d(TAG, String.format("Adding discount: %s, %s, %d, %f, %d", 
						discount.getName(), discount.getDescription(), discount.getPercentage(), discount.getPriceWithDiscount(), discount.getProduct()));
				addDiscount(discount, listProducts.get(discount.getProduct()));
				listDiscounts.add(discount);
			}
			
			// Init product tag
			
			// Init product location
			int productId, locationId;
			productId = 40; locationId = 5;
			for(int j = 0; j < 5; ++j)
			{
				productId += j;
				for(int i = 0; i < 20; ++i)
				{
					locationId += i;
					addProductLocation(productId, locationId);
				}
			}
			
			// Init product category
			
			// Init partner location
		}
	}
	
	public long addAddress(Address address)
	{
		long retValue;
		dbBazaaHelper.openDataBase(false);
		
		retValue = dbBazaaHelper.insertAddress(address.getStreet(), address.getNumber(), address.getCity(), address.getPostalCode(), address.getTownship(), address.getState(), address.getCountry());
		
		dbBazaaHelper.close();
		return retValue;
	}
	
	public long countAddresses()
	{
		long retValue;
		dbBazaaHelper.openDataBase(true);
		
		Cursor cursor = dbBazaaHelper.getAddresses();
		if(cursor != null)
			retValue = cursor.getCount();
		else
			retValue = 0;
		
		dbBazaaHelper.close();
		
		return retValue;
	}
	
	public long addLocation(Location location, Address address, Partner partner)
	{
		long retValue;
		long addressID;
		long partnerID;
		Cursor cursor;
		
		dbBazaaHelper.openDataBase(false);
		
		cursor = dbBazaaHelper.getAddress(address.getStreet(), address.getNumber(), address.getCity(), address.getPostalCode(), address.getTownship(), address.getState(), address.getCountry());
		if(cursor == null)
		{
			addressID = dbBazaaHelper.insertAddress(address.getStreet(), address.getNumber(), address.getCity(), address.getPostalCode(), address.getTownship(), address.getState(), address.getCountry());
		}
		else
		{
			cursor.moveToFirst();
			addressID = cursor.getLong(0); // return the value of the ID column
		}
		
		cursor = dbBazaaHelper.getPartner(partner.getName());
		if(cursor == null)
		{
			partnerID = dbBazaaHelper.insertPartner(partner.getName(), partner.getDescription(), 0); // NOTE: zero is set for contactID!
		}
		else
		{
			cursor.moveToFirst();
			partnerID = cursor.getLong(0); // return the value of the ID column
		}
		
		
		retValue = dbBazaaHelper.insertLocation(location.getName(), (double)location.getLongitude(), (double)location.getLatitude(), location.getOpeningHours(), (int)addressID, (int)partnerID);
		
		dbBazaaHelper.close();
		
		return retValue;
	}
	
	public long addCategory(Category category)
	{
		long retValue;
		
		dbBazaaHelper.openDataBase(false);
		
		retValue = dbBazaaHelper.insertCategory(category.getName());
		
		dbBazaaHelper.close();
		
		return retValue;
	}
	
	public long addContact(Contact contact)
	{
		long retValue;
		
		dbBazaaHelper.openDataBase(false);
		
		retValue = dbBazaaHelper.insertContact(contact.getTelephone/*String*/()/*.toString()*/, contact.getMobile/*String*/()/*.toString()*/, contact.getFax(), contact.getEmail/*String*/()/*.toString()*/, contact.getSite/*String*/()/*.toString()*/);
		
		dbBazaaHelper.close();
		
		return retValue;
	}
	
	public long addPartner(Partner partner, Contact contact)
	{
		long retValue;
		long contactID;
		Cursor cursor;
		
		dbBazaaHelper.openDataBase(false);
		
		cursor = dbBazaaHelper.getContact(contact.getTelephone(), contact.getMobile(), contact.getFax(), contact.getEmail(), contact.getSite());
		if(cursor == null)
		{
			contactID = dbBazaaHelper.insertContact(contact.getTelephone(), contact.getMobile(), contact.getFax(), contact.getEmail(), contact.getSite());
		}
		else
		{
			cursor.moveToFirst();
			contactID = cursor.getLong(0); // return the value of the ID column
		}
		
		retValue = dbBazaaHelper.insertPartner(partner.getName(), partner.getDescription(), (int)contactID);
		
		dbBazaaHelper.close();
		
		return retValue;
	}
	
	public long addDiscount(Discount discount, Product product)
	{
		long retValue;
		long productID;
		Cursor cursor;
		
		dbBazaaHelper.openDataBase(false);
		
		cursor = dbBazaaHelper.getProduct(product.getName());
		if(cursor != null)
		{
			cursor.moveToFirst();
			productID = cursor.getLong(0); // return the value of the ID column
		}
		else
		{
			productID = 0;
		}
		
		retValue = dbBazaaHelper.insertDiscount(discount.getName(), discount.getDescription(), (float)discount.getPercentage(), discount.getPriceWithDiscount().floatValue(), discount.getTimePeriod().getDateFrom(), discount.getTimePeriod().getDateTo(), (int)productID);
		
		return retValue;
	}
	
	public long addProduct(Product product, Partner partner)
	{
		long retValue;
		long partnerID = 0;
		Cursor cursor;
		
		dbBazaaHelper.openDataBase(false);
		
		cursor = dbBazaaHelper.getPartner(partner.getName());
		if(cursor != null)
		{
			cursor.moveToFirst();
			partnerID = cursor.getLong(0); // return the value of the ID column
		}
		
		retValue = dbBazaaHelper.insertProduct(product.getName(), product.getDescription(), (int)partnerID, (float)product.getPrice(), product.getCurrency(), 0);
		
		dbBazaaHelper.close();
		
		return retValue;	
	}
	
	public long addProductLocation(int productId, int locationId)
	{
		long retValue;
		
		dbBazaaHelper.openDataBase(false);
		
		retValue = dbBazaaHelper.insertProductLocation(locationId, productId);
		
		dbBazaaHelper.close();
		
		return retValue;
	}
}
